<?php

	/**
	 * @see Zend_Db_Table_Rowset_Abstract
	 */
	require_once 'Zend/Db/Table/Rowset/Abstract.php';
	
	
	class Bike_Db_Table_Rowset extends Zend_Db_Table_Rowset_Abstract
	{
		protected $_positions = array();
		protected $_mapperClass;

		public function __construct(array $config)
    	{    		parent::__construct($config);
            $this->setMapperClass(@$config['mapperClass']);
    	}

    	protected function setMapperClass($MapperClass)
        {
        	if(is_null($MapperClass))
    		{
    			require_once 'Zend/Db/Table/Rowset/Exception.php';
    			throw new Zend_Db_Table_Rowset_Exception("Undefined mapper class that you want to set!");
    		}
        	if(is_null($this->_mapperClass))
    		{
    			$this->_mapperClass = $MapperClass;
    			return $this;
    		}
    		require_once 'Zend/Db/Table/Rowset/Exception.php';
    		throw new Zend_Db_Table_Rowset_Exception("Mapper class already defined!");
        }

        protected function getMapperClass()
        {        	return $this->_mapperClass;
        }
        
        public function getMapper()
        {
        	return call_user_func(array($this->getMapperClass(), 'getInstance'));
        }

    	protected function _loadAndReturnRow($position)
	    {
	        if (!isset($this->_data[$position])) {
	            require_once 'Zend/Db/Table/Rowset/Exception.php';
	            throw new Zend_Db_Table_Rowset_Exception("Data for provided position does not exist");
	        }

	        // do we already have a row object for this position?
	        if (empty($this->_rows[$position])) {
	            $this->_rows[$position] = new $this->_rowClass(
	                array(
	                    'table'    => $this->_table,
	                    'data'     => $this->_data[$position],
	                    'stored'   => $this->_stored,
	                    'readOnly' => $this->_readOnly,
	                    'mapperClass' => $this->getMapperClass(),
	                    //'select'   => $this->getSelect(),
	                )
	            );
	        }

	        // return the row object
	        return $this->_rows[$position];
	    }

		public function __call($method, array $args)
    	{    		$matches = array();

    		/**
	         * Recognize methods getRowBy<FieldName>()
	         */
    		if(preg_match('/^getRowBy([\w\d]+)$/', $method, $matches))
    		{
	            return $this->getRowByField(Bike_String::factory($matches[1])->stripCamelCase(), $args[0], @$args[1]);
	        }
	        
	        /**
	         * Recognize methods getRowsBy<FieldName>()
	         */
	        if(preg_match('/^getRowsBy([\w\d]+)$/', $method, $matches))
	        {
	        	return $this->getRowsByField(Bike_String::factory($matches[1])->stripCamelCase(), $args[0], @$args[1]);
	        }
	        
	        require_once 'Zend/Db/Table/Rowset/Exception.php';
	        throw new Zend_Db_Table_Rowset_Exception(sprintf('Undefined method %s', $method));
    	}

		public function getRowByField($FieldName, $FieldValue, $Seek = False)
	    {
	        $rows = $this->getRowsByField($FieldName, $FieldValue, $Seek);
	        
	    	return reset($rows);
	    }
	    
	    public function getRowsByField($FieldName, $FieldValue, $Seek = False)
	    {
	    	if(!isset($this->_positions[$FieldName]) || !is_array($this->_positions[$FieldName]))
	    	{
	    		$this->rewind();
	    		while($this->valid())
	    		{
	    			$Row = $this->current();
	    			if(!is_array($this->_positions[$FieldName][$Row->$FieldName]))
	    			{
	    				$this->_positions[$FieldName][$Row->$FieldName] = array();
	    			}
	    			array_push($this->_positions[$FieldName][$Row->$FieldName], $this->key());
	    			$this->next();
	    		}
	    	}
	    	
	    	if(!isset($this->_positions[$FieldName][$FieldValue]))
	    	{
	    		require_once 'Zend/Db/Table/Rowset/Exception.php';
	    		throw new Zend_Db_Table_Rowset_Exception("Undefined value ".$FieldValue." for field ".$FieldName);
	    	}
	    	$positions = @$this->_positions[$FieldName][$FieldValue];
	    	$rows = array();
	    	foreach($positions as $key)
	    	{
	    		array_push($rows, $this->getRow($key, $Seek));
	    	}
	    	
	    	return $rows;
	    }
	    
	    public function getMultiOptions($keyFieldName, $valueFieldName)
	    {
	    	$keyFieldName = Bike_String::factory($keyFieldName)->toCamelCase();
	    	$valueFieldName = Bike_String::factory($valueFieldName)->toCamelCase();
	    	$multiOptions = array();
	    	$this->rewind();
	    	$keyFieldNameMethod = 'get'.$keyFieldName;
	    	$valueFieldNameMethod = 'get'.$valueFieldName;
	    	while($this->valid())
	    	{
	    		$Row = $this->current();
	    		$multiOptions[$Row->$keyFieldNameMethod()] = $Row->$valueFieldNameMethod();
	    		$this->next();
	    	}
	    	return $multiOptions;
	    }

	    public function setReadOnly()
	    {	    	$this->_readOnly = True;
	    	return $this;
	    }
	}
